<?php


namespace App\Game\Core;


use App\Game\Conf\GameProgress;
use App\Game\Conf\SubCmd;
use App\Model\User;
use App\Service\FreeOrderTaskService;
use App\Service\TaskCenterService;

class Room
{

    /**
     * * 检查用户的积分
     * @param $account
     * @return bool
     */
    public function checkScore($account)
    {
        $user_conf = config('user');
        $user_info = User::userInfo($account);
        if (($user_info['score']) > $user_conf['create_room_score']) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 检查有无正在游戏房间
     * @param $account
     * @return bool
     */
    public static function checkPlaying($account)
    {
        $game_conf = config('game');
        $redis = redis();
        $user_map_key = sprintf($game_conf['user_room'], $account);
        if (!$redis->exists($user_map_key)) {
            return false;
        }
        $room_no = $redis->get($user_map_key);
//        $type = getGameProgressType($room_no);
//        if ($type) {//单机
//            clearRoomDataAll($room_no);
//            return false;
//        }
        $room_wait_key = sprintf($game_conf['user_room_wait'], $room_no);
        if (!$redis->exists($room_wait_key)) {
            return false;
        }
        return $room_no;
    }

    //创建房间号，自增
    public static function createRoomNo()
    {
        $game_conf = config('game');
        $key = $game_conf['user_room_no'];
        if (redis()->exists($key)) {
            $room_no = redis()->incr($key);
        } else {
            $room_no = intval(10001);
            redis()->set($key, $room_no);
        }
//        $master = rand(1, 4);
//        self::updateRoomData($room_no, ['master' => $master]);
        return $room_no;
    }


    //获取等待房间队列
    public static function getWaitRoom()
    {
        $game_conf = config('game');
        $key = $game_conf['wait_room_list'];
        $res = redis()->rPop($key);
        if ($res) {
            return json_decode($res, true);
        }
        return [];
    }

    //添加等待房间队列
    public static function createWaitRoom($room_no, $playersData)
    {
        $game_conf = config('game');
        $key = $game_conf['wait_room_list'];
        $data = json_encode(['room_no' => $room_no, 'players' => $playersData]);
        redis()->lPush($key, $data);
    }

    //重新添加等待房间队列
    public static function addWaitRoom($room_no, $playersData)
    {
        $game_conf = config('game');
        $key = $game_conf['wait_room_list'];
        $data = json_encode(['room_no' => $room_no, 'players' => $playersData]);
        redis()->rPush($key, $data);
    }

    public static function getRoomPlayers($room_no): array
    {
        $waiters = self::getRoomWait($room_no);
        return $waiters;
    }

    public static function getRoomUserData($room_no, $account)
    {
        $game_conf = config('game');
        $room_data_key = sprintf($game_conf['user_room_data'], $room_no);
        $userData = redis()->hGet($room_data_key, (string)$account);
        if (!$userData) {
            return [];
        }
        return json_decode($userData, true);
    }

    public static function getRoomNoByAccount($account)
    {
        $game_conf = config('game');
        $user_map_key = sprintf($game_conf['user_room'], $account);
        return redis()->get($user_map_key);
    }

    /**
     * 绑定用户和房间
     * @param $account
     * @param $room_no
     */
    public static function addUserRoomMap($account, $room_no)
    {
        $game_conf = config('game');
        $room_map_conf = $game_conf['user_room'];
        $room_map_key = sprintf($room_map_conf, $account);
        redis()->set($room_map_key, (int)$room_no);// 绑定用户房间号
    }

    //移除用户-房间的绑定关系
    public static function removeUserRoomMap($account, $room_no)
    {
        $game_conf = config('game');
        $room_map_conf = $game_conf['user_room'];
        $room_map_key = sprintf($room_map_conf, $account);
        redis()->del($room_map_key, (int)$room_no);// 绑定用户房间号
    }

    /**
     * 绑定房间和用户
     * @param $account
     * @param $room_no
     */
    public static function addRoomUser($account, $room_no)
    {
        $game_conf = config('game');
        $room_wait_conf = $game_conf['user_room_wait'];
        $room_wait_key = sprintf($room_wait_conf, $room_no);
        $json_wait_room = redis()->get($room_wait_key);
        $arr_wait_room = [];
        if ($json_wait_room) {
            $arr_wait_room = json_decode($json_wait_room, true);
            if (!in_array($account, $arr_wait_room)) {
                array_push($arr_wait_room, $account);
            }
        }
        redis()->set($room_wait_key, json_encode($arr_wait_room));// 绑定用户房间号
    }

    /**
     * 绑定桌位号
     * @param $account
     * @param $room_no
     */
    public static function addRoomChair($account, $room_no)
    {
        $game_conf = config('game');
        $room_chair_key = sprintf($game_conf['user_room_chair'], $room_no);
        $room_chair_data = [];
        $chair_id = 1;
        if (redis()->exists($room_chair_key)) {
            $room_chair_data = json_decode(redis()->get($room_chair_key), true);
            if (!in_array(1, $room_chair_data)) {
                $room_chair_data[$account] = 1;
            } elseif (!in_array(2, $room_chair_data)) {
                $room_chair_data[$account] = 2;
                $chair_id = 2;
            } elseif (!in_array(3, $room_chair_data)) {
                $room_chair_data[$account] = 3;
                $chair_id = 3;
            } elseif (!in_array(4, $room_chair_data)) {
                $room_chair_data[$account] = 4;
                $chair_id = 4;
            }
        } else {
            $room_chair_data[$account] = 1;
        }
        redis()->set($room_chair_key, json_encode($room_chair_data));// 绑定用户房间号桌位号
        return $chair_id;
    }

    public static function getRoomChairs($room_no)
    {
        $game_conf = config('game');
        $room_chair_key = sprintf($game_conf['user_room_chair'], $room_no);
        if (redis()->exists($room_chair_key)) {
            return json_decode(redis()->get($room_chair_key), true);
        } else {
            return [];
        }
    }

    public static function getRoomWait($room_no)
    {
        $game_conf = config('game');
        $key = sprintf($game_conf['user_room_wait'], $room_no);
        if (redis()->exists($key)) {
            return json_decode(redis()->get($key), true);
        }
        return [];
    }

    public static function addRoomWait($room_no, $account)
    {
        $game_conf = config('game');
        $room_wait_key = sprintf($game_conf['user_room_wait'], $room_no);
        $waiters = self::getRoomWait($room_no);
        $waiters[] = $account;
        redis()->set($room_wait_key, json_encode($waiters, JSON_UNESCAPED_SLASHES));
    }

    public static function getRoomTotal($room_no)
    {
        $game_conf = config('game');
        $key = sprintf($game_conf['user_room_total'], $room_no);
        if (redis()->exists($key)) {
            return redis()->sMembers($key);
        }
        return [];
    }

    public static function addRoomTotal($room_no)
    {
        $game_conf = config('game');
        redis()->sAdd($game_conf['user_room_total'], $room_no);
    }

    public static function getRoomMaster($room_no)
    {
        $master = self::getRoomData($room_no, 'next_master');
        if (empty($master)) {
            $master = self::getRoomData($room_no, 'master');
        }
        return $master;
    }

    public static function updateRoomData($room_no, $params)
    {
        $game_conf = config('game');
        $room_data_key = sprintf($game_conf['user_room_data'], $room_no);
        foreach ($params as $key => $val) {
            $value = $val;
            if (is_array($val)) {
                $value = json_encode($val, true);
            }
            redis()->hSet($room_data_key, (string)$key, $value);
        }
    }

    public static function generateRoomDatagenerateRoomData($room_no, $game_type = 0)
    {
        $params = array(
            'room_no' => $room_no,
            'hand' => [],   //底牌
            'master' => 1,  //庄家座椅号
            'is_game_over' => 0,
            'game_type' => $game_type, //游戏类型 0.普通游戏 1.大奖赛
        );
        self::updateRoomData($room_no, $params);
    }

    public static function getRoomData($room_no, $child_key = '')
    {
        $game_conf = config('game');
        $room_data_key = sprintf($game_conf['user_room_data'], $room_no);

        if ($child_key) {
            $res = redis()->hGet($room_data_key, (string)$child_key);
            if ($res == false) {
                return [];
            }
            return $res;
        }

        if (redis()->exists($room_data_key)) {
            return redis()->hGetAll($room_data_key);;
        } else {
            return [];
        }
    }


    public static function cleanRoom($room_no)
    {
        //清除房间数据
        resetRoomData($room_no);
        //清除房间等待数据
        clearRoomWait($room_no);
        //清除房间机器人
        removeRoomRobot($room_no);
        //重置计数器
        delOperCounter($room_no);
        //清除定缺数据
        resetRoomColors($room_no);
        //清除座位数据
        resetRoomChairs($room_no);
        //清除换牌数据
        resetRoomChangeCards($room_no);
        //清除检查胡碰杠数据
        resetCheckHpg($room_no);
        //清除准备数据
        resetGamePrepare($room_no);
        //清除游戏阶段数据
        resetGameProgress($room_no);
        //清除定时器
        putTimerDel($room_no);
    }

    public static function bindUserData($room_no, $users = [])
    {
        if (empty($users)) {
            return;
        }
        foreach ($users as $account) {
            if (!Robot::isRobot($room_no, $account)) {
                self::addUserRoomMap($account, $room_no);
            }
            self::addRoomWait($room_no, $account);
            self::addRoomChair($account, $room_no);
        }
    }

    public static function gameOver($room_no)
    {
        $game_conf = config('game');
        $room_data_key = sprintf($game_conf['user_room_data'], $room_no);
        if (redis()->exists($room_data_key)) {
            $room_data = redis()->hGetAll($room_data_key);
            $uinfo_arr = json_decode($room_data['uinfo'], true);
            $returnData = [];
            $chairs = getRoomChairs($room_no);
            foreach ($chairs as $account => $chair_id) {
                // {"chair_id":1,"score":64,"nickname":"GGYY","total_bonus":16,"detial_list":[{"reward":"清一色","bonus":8},......]}
                $userData = json_decode($room_data[$account], true);
                $total_bonus = 0;
                $hu_detail = isset($userData['hu_detail']) ? $userData['hu_detail'] : [];
                if (!empty($hu_detail)) {
                    $tem = [];
                    foreach ($hu_detail as $v) {
                        $total_bonus += $v['bonus'];
                        $tem[] = $v;
                    }
                    $hu_detail = $tem;
                }
                $userInfo = User::userInfo($account);

                $returnData[] = [
                    'chair_id' => $chair_id,
                    'account' => $account,
                    'score' => $uinfo_arr[$account]['score'],
                    'nickname' => filterNickname($userInfo['nickname']),
                    'total_bonus' => $total_bonus,
                    'detial_list' => $hu_detail,
                    'is_robot' => $userData['is_robot']
                ];
            }

            dd('gameOver returnData', $returnData);

            setGameProgress($room_no, GameProgress::GAME_CACULAR);

            //更新用户积分并记录流水
            $userArr = updateScore($room_no, $returnData);
            //更新每日任务
            TaskCenterService::updateMjDayTask($userArr);
            // 更新成长任务
            TaskCenterService::updateMjGrow($userArr);
            //更新免单任务
            FreeOrderTaskService::updateMjFreeOrderTask($userArr);

            if ($room_data['game_type'] == 1) {//大奖赛
                Djs::roundOver($room_no, $returnData);
                return;
            }
            //全员发送结算通知
            Message::broadCast($room_no, $returnData, SubCmd::SUB_GAME_CACULAR);

            //剔除所有机器人
            kickOutRobot($room_no);

            //剔除托管或掉线玩家
            kickOutTakerOverPlayers($room_no);

            $nextMaster = isset($room_data['next_master']) ? $room_data['next_master'] : 0;
            if (!$nextMaster) {
                $nextMaster = $room_data['master'] + 1;
                $nextMaster = $nextMaster > 4 ? $nextMaster - 4 : $nextMaster;
            }
            //重置对应游戏数据
            $new_room_data = [
                'master' => $nextMaster,
                'is_game_over' => 1,
                'room_no' => $room_no,
            ];

            resetRoomData($room_no, $new_room_data);

            //重置计数器
            delOperCounter($room_no);
            //清除定缺数据
            resetRoomColors($room_no);
            //清除座位数据
            resetRoomChairs($room_no);
            //清除换牌数据
            resetRoomChangeCards($room_no);
            //清除检查胡碰杠数据
            resetCheckHpg($room_no);
            //清除准备数据
            resetGamePrepare($room_no);
            //清除房间数据
            resetGameProgress($room_no);
            //清除定时器
            putTimerDel($room_no);
        }

    }


}
